package com.lys.mixin.entity;


import com.lys.util.PersistentProjectileEntityData;
import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

@Mixin(PersistentProjectileEntity.class)
public abstract class PersistentProjectileEntityMixin implements PersistentProjectileEntityData {

    private int explosionLevel;

    private boolean isExplode;

    PersistentProjectileEntity persistentProjectileEntity = (PersistentProjectileEntity) (Object) this;

    private ScheduledExecutorService executor;

    private ScheduledFuture<?> future;

    private long startTime;

    /**
     * 当箭矢命中实体时的判断
     */
    @Inject(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/PersistentProjectileEntity;onHit(Lnet/minecraft/entity/LivingEntity;)V"), locals = LocalCapture.CAPTURE_FAILHARD)
    protected void injectOnEntityHit(EntityHitResult entityHitResult, CallbackInfo ci, Entity entity2) {
        if (explosionLevel > 0 && isExplode) {
            this.isExplode = false;
            Text entityName = entity2.getName();
            // 记录开始时间
            startTime = System.currentTimeMillis();
            // 创建一个计时器，在三秒后触发爆炸
            executor = Executors.newSingleThreadScheduledExecutor();
            future = executor.scheduleWithFixedDelay(() -> {
                // 计算剩余秒数
                long remainingTime = calculateRemainingTime();
                if (remainingTime <= 0 && entity2.isAlive()) {
                    //剩余时间小于等于0，触发爆炸并清除箭矢
                    this.explode(entity2.getX(), entity2.getY(), entity2.getZ(), this.explosionLevel);
                    persistentProjectileEntity.remove(Entity.RemovalReason.DISCARDED);
                    //设置实体回原来的名字并且不在显示
                    entity2.setCustomName(entityName);
                    entity2.setCustomNameVisible(false);
                    future.cancel(false); // 取消计时器
                } else {
                    // 更新箭矢的显示名称
                    String displayName =  String.format("0%d:%02d", remainingTime / 1000,(remainingTime % 1000)/10);
                    entity2.setCustomName(Text.literal(displayName).setStyle(Style.EMPTY.withColor(Formatting.RED)));
                    entity2.setCustomNameVisible(true);
                }
            }, 0, 10, TimeUnit.MILLISECONDS);
        }
    }

    /**
     * 当箭矢命中方块时的判断
     */
    @Inject(method = "onBlockHit", at = @At(value = "TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
    protected void injectOnBlockHit(BlockHitResult blockHitResult, CallbackInfo ci) {
        BlockPos blockPos = blockHitResult.getBlockPos();
        if (explosionLevel > 0 && isExplode) {
            this.isExplode = false;
            // 记录开始时间
            startTime = System.currentTimeMillis();
            // 创建一个计时器，在三秒后触发爆炸
            executor = Executors.newSingleThreadScheduledExecutor();
            future = executor.scheduleWithFixedDelay(() -> {
                // 计算剩余秒数
                long remainingTime = calculateRemainingTime();
                if (remainingTime <= 0 && persistentProjectileEntity.isAlive()) {
                    // 剩余时间小于等于0，触发爆炸并清除箭矢
                    this.explode(blockPos.getX(), blockPos.getY(), blockPos.getZ(), this.explosionLevel);
                    persistentProjectileEntity.remove(Entity.RemovalReason.DISCARDED);
                    future.cancel(false); // 取消计时器
                } else {
                    // 更新箭矢的显示名称
                    String displayName =  String.format("0%d:%02d", remainingTime / 1000, (remainingTime % 1000)/10);
                    persistentProjectileEntity.setCustomName(Text.literal(displayName).setStyle(Style.EMPTY.withColor(Formatting.RED)));
                    persistentProjectileEntity.setCustomNameVisible(true);
                }
            }, 0, 10, TimeUnit.MILLISECONDS);
        }

    }

    @Inject(method = "writeCustomDataToNbt", at = @At("HEAD"))
    protected void injectWriteCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) {
        nbt.putInt("explosiveLevel", explosionLevel);
        nbt.putBoolean("isExplode", isExplode);
        nbt.putLong("startTime", startTime);
    }

    @Inject(method = "readCustomDataFromNbt", at = @At("HEAD"), cancellable = true)
    protected void injectReadCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) {
        if (nbt.contains("explosiveLevel")) {
            this.explosionLevel = nbt.getInt("explosiveLevel");
        }
        if (nbt.contains("isExplode")) {
            this.isExplode = nbt.getBoolean("isExplode");
        }
        if (nbt.contains("startTime")) {
            this.startTime = nbt.getLong("startTime");
        }
        ci.cancel();
    }

    @Override
    public void explode(double x, double y, double z, int explosiveArrowLevel) {
        World world = persistentProjectileEntity.getWorld();
        world.createExplosion(persistentProjectileEntity, x, y, z, explosiveArrowLevel, World.ExplosionSourceType.TNT);
    }

    public long calculateRemainingTime() {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - startTime;
        return 3000 - elapsedTime;
    }
}
